//build: 20240528
import { calibrationClass } from './libvbar-m-dxcapturer_calibration.so'
import capturer from '../dxmodules/dxCapturer.js'
import dxMap from './dxMap.js'
import log from './dxLogger.js'
import bus from './dxEventBus.js'
const calibrationObj = new calibrationClass();
const map = dxMap.get('default')
const calibration = {}
let cnt = 0, startTime = 0;

/**
 * calibration initialization
 * @returns true/false
 */
calibration.init = function () {
	return calibrationObj.init();
}

/**
 * calibration deinitialization
 * @returns true/false
 */
calibration.deinit = function () {
	return calibrationObj.deinit();
}

/**
 * Identification and calibration (align graph paper with the squares on the screen).
 * @param {number} imageRgb Image pointer (required)
 * @param {number} imageNir Image pointer (required)
 * @param {number} cnt Number of calibrations (required) (0: first calibration, 1: second calibration)
 * @returns true/false
 */
calibration.calibrationFromImage = function (imageRgb, imageNir, cnt) {
	return calibrationObj.calibrationFromImage(imageRgb, imageNir, cnt);
}

/**
 * Calculate and store calibration results
 * @param {number} imageNir Image pointer (required)
 * @param {string} path Storage path (required)
 * @returns true/false
 */
calibration.getMap = function (imageRgb, imageNir,cnt, path) {
	return calibrationObj.getMap(imageRgb, imageNir,cnt, path);
}

/**
 * Get the drawing calibration UI box information
 * @param {number} cnt Number of calibrations (required) (0: first calibration, 1: second calibration)
 * @param {number} type Landscape or portrait orientation, required (1: landscape, 0: portrait)
 * @returns {x:x-axis,y:y-axis,w:width,h:height}
 */
calibration.getBox = function (cnt, type) {
	let box = calibrationObj.getBox(cnt);
	let coordinate = {
		x: type == 1 ? box.x : box.y,
		y: type == 1 ? box.y : box.x,
		w: type == 1 ? box.w : box.h,
		h: type == 1 ? box.h : box.w
	}
	return coordinate;
}

calibration.RECEIVE_MSG = '__calibration__MsgReceive'

/**
 * Simplify the use of the cameraCalibration component; there's no need to poll for data, as data is sent out via eventbus.
 * Since the calibrationFromImage method is thread-blocking, it must be executed in a new thread; otherwise, it will block other threads.
 * The `run` function will execute only once.
 * @param {object} options Configuration parameters
 * @param {string} options.capturerRgbId      Required, RGB image handle ID
 * @param {string} options.capturerNirId      Required, .nir image handle ID
 * @param {number} options.timeout      	The unit is seconds. This is optional (default is 20 seconds). It represents the timeout period for calibration. If two calibrations are not completed within this timeframe, the calibration fails and the thread terminates. To recalibrate, the `run` method must be executed again.
 */
calibration.run = function (options) {
	if (options === undefined || options.length === 0) {
		throw new Error("dxCameraCalibration.run:'options' parameter should not be null or empty")
	}
	if (options.capturerRgbId === undefined || options.capturerRgbId === null || options.capturerRgbId.length <= 0) {
		throw new Error("dxCameraCalibration.run:'capturerRgbId' should not be null or empty")
	}
	if (options.capturerNirId === undefined || options.capturerNirId === null || options.capturerNirId.length <= 0) {
		throw new Error("dxCameraCalibration.run:'capturerNirId' should not be null or empty")
	}
	options.timeout = options.timeout ? options.timeout : 20
	try {
		if(startTime == null || startTime == 0){
			startTime = new Date().getTime()
		}
        let imageRgb = capturer.readImage(options.capturerRgbId)
        let imageNir = capturer.readImage(options.capturerNirId)
        let res = this.calibrationFromImage(imageRgb, imageNir, cnt)
        if (res) {
            if (cnt >= 1) {
                log.info("Calibration ends after two successful calibrations.")
                let path = "/etc/.cameraCalibration"
                if(options.path && options.path.length > 0){
                    path = options.path
                }
                this.getMap(imageRgb, imageNir, cnt, path)
                bus.fire(this.RECEIVE_MSG, "success1")
                capturer.destroyImage(imageRgb)
                capturer.destroyImage(imageNir)
				cnt = 0;
				startTime = 0;
                return "success1"
            }
            log.info("No." + (cnt + 1) + "Calibration successful.")
            bus.fire(this.RECEIVE_MSG, "success0")
            cnt += 1
            log.info("Begin the first" + (cnt + 1) + "Sub-calibration")
            return "success0"
        } else {
            log.error("No." + (cnt + 1) + "Calibration failed, retrying.")
        }
        capturer.destroyImage(imageRgb)
        capturer.destroyImage(imageNir)
        let endTime = new Date().getTime()
        if (endTime - startTime > options.timeout * 1000) {
            log.error('Calibration timed out, please re-perform the calibration.')
            bus.fire(this.RECEIVE_MSG, "timeout")
            cnt = 0
			startTime = 0;
            return "timeout"
        }
        return "failed"
    } catch (error) {
        log.error(error)
    }
}

export default calibration;